package net.pimpas.web.jsf.renderers.commandlink.html;

import java.io.IOException;
import java.util.Iterator;

import javax.faces.component.UIComponent;
import javax.faces.component.UIParameter;
import javax.faces.component.html.HtmlCommandLink;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;

import net.pimpas.web.jsf.components.ajax.UIAjax;
import net.pimpas.web.jsf.util.ComponentUtils;

import org.apache.myfaces.shared_impl.config.MyfacesConfig;
import org.apache.myfaces.shared_impl.renderkit.RendererUtils;
import org.apache.myfaces.shared_impl.renderkit.html.HTML;
import org.apache.myfaces.shared_impl.renderkit.html.HtmlLinkRendererBase;
import org.apache.myfaces.shared_impl.renderkit.html.HtmlRendererUtils;
import org.apache.myfaces.shared_impl.renderkit.html.util.FormInfo;

public class HtmlCommandLinkRenderer extends HtmlLinkRendererBase {

	@Override
	public void encodeBegin(FacesContext facesContext, UIComponent component) throws IOException {
		
	}
	
	@Override
	public void encodeEnd(FacesContext facesContext, UIComponent component) throws IOException {
		
		super.encodeBegin(facesContext, component);
		super.encodeEnd(facesContext, component);
	}
	
	/**
	 * Extracted from myfaces-1.1.5-SNAPSHOT
	 */
	private void renderLinkParameter(String name,
			Object value,
			StringBuffer onClick,
			String jsForm,
			UIComponent nestingForm)
	{
		if (name == null)
		{
			throw new IllegalArgumentException("Unnamed parameter value not allowed within command link.");
		}
		onClick.append(jsForm);
		onClick.append(".elements['").append(name).append("']");
		String strParamValue = value != null ? org.apache.myfaces.shared_impl.renderkit.html.util.HTMLEncoder.encode(value.toString(), false, false) : "";
		onClick.append(".value='").append(strParamValue).append("';");

		addHiddenCommandParameter(FacesContext.getCurrentInstance(), nestingForm, name);
	}

	@Override
	protected void renderJavaScriptAnchorStart(FacesContext facesContext, ResponseWriter writer, UIComponent component, String clientId) throws IOException {
		// have ajax as child?!
		if(ComponentUtils.getComponentByClass(component, UIAjax.class) == null) {
			super.renderJavaScriptAnchorStart(facesContext, writer, component, clientId);
			return;
		}
		// hax ajax
		/**
		 * Extracted from myfaces-1.1.5-SNAPSHOT
		 */

		//Find form
		FormInfo formInfo = findNestingForm(component, facesContext);
		if (formInfo == null)
		{
			String path = RendererUtils.getPathToComponent(component);
			String msg = "Change component/tag '" + clientId + "' from javax.faces.*/<h:tagName /> " +
			"to org.apache.myfaces.*/<t:tagName />, or embed it in a form.  This is not a bug. " +
			"Please see: http://wiki.apache.org/myfaces/Upgrading_to_Tomahawk_1.1.3 " +
			"The path to this component is " + path ;
			throw new IllegalArgumentException(msg);
		}
		UIComponent nestingForm = formInfo.getForm();
		String formName = formInfo.getFormName();

		StringBuffer onClick = new StringBuffer();

		String commandOnclick;
		if (component instanceof HtmlCommandLink)
		{
			commandOnclick = ((HtmlCommandLink)component).getOnclick();
		}
		else
		{
			commandOnclick = (String)component.getAttributes().get(HTML.ONCLICK_ATTR);
		}

		//call the clear_<formName> method
		onClick.append(HtmlRendererUtils.getClearHiddenCommandFormParamsFunctionName(formName)).append("();");

		String jsForm = "document.forms['" + formName + "']";

		if (MyfacesConfig.getCurrentInstance(facesContext.getExternalContext()).isAutoScroll())
		{
			//TODO fix autoscroll for 1.1.5
			//org.apache.myfaces.shared_impl.renderkit.html.util.JavascriptUtils.appendAutoScrollAssignment(onClick, formName);
		}

		//add id parameter for decode
		String hiddenFieldName = HtmlRendererUtils.getHiddenCommandLinkFieldName(formInfo);
		onClick.append(jsForm);
		onClick.append(".elements['").append(hiddenFieldName).append("']");
		onClick.append(".value='").append(clientId).append("';");
		addHiddenCommandParameter(facesContext, nestingForm, hiddenFieldName);

		//add child parameters
		for (Iterator it = getChildren(component).iterator(); it.hasNext(); )
		{
			UIComponent child = (UIComponent)it.next();
			if (child instanceof UIParameter)
			{
				String name = ((UIParameter)child).getName();
				Object value = ((UIParameter)child).getValue();

				renderLinkParameter(name, value, onClick, jsForm, nestingForm);
			}
		}

		// target
		// todo: can we eliminate the if and rely on the second call only ?
		// see MYFACES-310, specifically the comment by Emond Papegaaij. Will try
		// after testing framework is in place & tests are written.
		String target = null;
		if (component instanceof HtmlCommandLink)
		{
			target = ((HtmlCommandLink)component).getTarget();
		}
		else
		{
			target = (String)component.getAttributes().get(HTML.TARGET_ATTR);
		}
		if (target != null && target.trim().length() > 0) {
			onClick.append(jsForm);
			onClick.append(".target='");
			onClick.append(target);
			onClick.append(";");
		}

		if (commandOnclick != null)
			onClick.append(commandOnclick);
		
		writer.startElement(HTML.ANCHOR_ELEM, component);
		writer.writeURIAttribute(HTML.HREF_ATTR, "javascript:void(0)", null);
		writer.writeAttribute(HTML.ONCLICK_ATTR, onClick.toString(), null);
	}
}